﻿#include "SEAPointJunctionDialog.h"
#include "ui_SEAPointJunctionDialog.h"
#include "SEAJunctionUserDefWidget.h"

#include "OperatorsInterface/ParaWidgetInterfaceOperator.h"

#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITK_Kernel/FITKCore/FITKVec3D.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsSEAModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAbstractSEASubSys.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEAAbstractJunction.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEAJunctionPoint.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscNodeList.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsPhysics.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbsPhysicsProp.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbsShellPhysicsProp.h"

#include <QList>
#include <QMessageBox>

#define SEAPointJunction_SubSysPos Qt::UserRole
#define SEAPointJunction_PointPos Qt::UserRole+1

namespace GUI
{
    SEAPointJunctionDialog::SEAPointJunctionDialog(int dataID, EventOper::ParaWidgetInterfaceOperator * oper, bool isCreate) :
        GUIJunctionDialogBase(dataID, oper, isCreate, FITKAPP->getGlobalData()->getMainWindow())
    {
        _ui = new Ui::SEAPointJunctionDialog();
        _ui->setupUi(this);

        if (isCreate == false) {
            _currentDataID = dataID;
        }

        init();
    }

    SEAPointJunctionDialog::~SEAPointJunctionDialog()
    {
        if (_userDefWidget) {
            delete _userDefWidget;
            _userDefWidget = nullptr;
        }
        if (_ui) {
            delete _ui;
            _ui = nullptr;
        }
    }

    void SEAPointJunctionDialog::init()
    {
        QStringList connectHeader;
        connectHeader << QString(tr("Connections")) << QString(tr("Radius")) << QString(tr("Ove")) << QString(tr("Alpha"));
        _ui->tableWidget_Connect->setColumnCount(4);
        _ui->tableWidget_Connect->setHorizontalHeaderLabels(connectHeader);
        //自适应
        _ui->tableWidget_Connect->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
        //隐藏行表头
        _ui->tableWidget_Connect->verticalHeader()->setVisible(false);
        _ui->tableWidget_Connect->horizontalHeader()->setSectionResizeMode(2, QHeaderView::ResizeToContents);

        QStringList nodeHeader;
        nodeHeader << QString(tr("ID")) << QString(tr("Z")) << QString(tr("Y")) << QString(tr("Z"));
        _ui->tableWidget_Node->setRowCount(1);
        _ui->tableWidget_Node->setColumnCount(4);
        _ui->tableWidget_Node->setHorizontalHeaderLabels(nodeHeader);
        //自适应
        _ui->tableWidget_Node->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

        _ui->label_GeneralImage->setPixmap(QPixmap(":/icons/SEA_Junction_Point.png"));

        _ui->checkBox_EnabledJunction->setChecked(true);

        _userDefWidget = new SEAJunctionUserDefWidget(this);
        _ui->gridLayout_UserDef->addWidget(_userDefWidget);

        if (_isCreate) {
            InitCreate();
            setWindowTitle(QString("SEA Point Junction Create"));
        }
        else {
            InitEdit();
            setWindowTitle(QString("SEA Point Junction Edit"));
            _ui->lineEdit_Name->setEnabled(false);
        }
    }

    void SEAPointJunctionDialog::setSubsysIDs(QList<QPair<int, int>> subsys)
    {
        if (_SEAModel == nullptr) return;
        //SEA模型管理器
        Acoustics::FITKAcousticsSEASubSysManager* manager = _SEAModel->getSEASubSysManager();
        if (!manager) return;
        //遍历所有子系统
        QList<Acoustics::FITKSEAJunPointConStr> connects = {};
        QList<int> subSysIDs = {};
        for (QList<QPair<int, int>>::iterator iter = subsys.begin(); iter != subsys.end(); ++iter)
        {
            int subsysID = iter->first, pointID = iter->second;
            Acoustics::FITKAbstractSEASubSys* subSysData = manager->getDataByID(subsysID);
            if (!subSysData) continue;
            QList<int> sysPointIDs = subSysData->getNodeIDs();
            if (!sysPointIDs.contains(pointID))continue;
            //判断子系统是否被使用
            bool isUseSub = false;
            for (Acoustics::FITKSEAJunPointConStr str : connects) {
                if (str._subSysID == subsysID) {
                    isUseSub = true;
                    break;
                }
            }
            if (isUseSub == true)continue;

            //子系统id与点id
            Acoustics::FITKSEAJunPointConStr conStr;
            conStr._subSysID = subSysData->getDataObjectID();
            conStr._pointID = pointID;
            subSysIDs.append(subsysID);

            Acoustics::FITKAcousticsPhysicsPropManager* physicsManager = _physics->getPhysicsPropManager();
            if (physicsManager == nullptr)continue;
            int physicsId = subSysData->getPropSectionID();

            if (subSysData->getSEASubSysType() == Acoustics::FITKAbstractSEASubSys::SEABeam) {
                //梁的半径
                auto physicsData = dynamic_cast<Acoustics::FITKAcousticsAbsShellPhysicsProp*>(physicsManager->getDataByID(physicsId));
                if (physicsData) {
                    /*conStr._radius = physicsData->getShellThickness();*/
                }
            }
            else {
                //板厚度
                auto physicsData = dynamic_cast<Acoustics::FITKAcousticsAbsShellPhysicsProp*>(physicsManager->getDataByID(physicsId));
                if (physicsData) {
                    conStr._radius = physicsData->getShellThickness();
                }
                //角度
            }

            //存储连接信息
            connects.append(conStr);
        }
        updateConnectTable(connects);
        if (_userDefWidget) {
            _userDefWidget->initTable(subSysIDs);
        }
    }

    void SEAPointJunctionDialog::setNode(int nodeID)
    {
        updateNodeTable(nodeID);
    }

    void SEAPointJunctionDialog::on_pushButton_Ok_clicked()
    {
        if (_isCreate) {
            if (OKCreate() == false)return;
        }
        else {
            if (OKEdit() == false)return;
        }
        if (_oper) {
            _oper->setArgs(objID_String, _currentDataID);
            _oper->execProfession();
        }
        this->accept();
    }

    void SEAPointJunctionDialog::on_pushButton_Cancel_clicked()
    {
        this->reject();
    }

    void SEAPointJunctionDialog::slotAlphaOveCheck()
    {
        QCheckBox* checkBox = dynamic_cast<QCheckBox*>(sender());
        if (checkBox == nullptr)return;
        int rowIndex = checkBox->property("row").toInt();
        if (rowIndex < 0 || rowIndex >= _ui->tableWidget_Connect->rowCount())return;

        QTableWidgetItem* item = _ui->tableWidget_Connect->item(rowIndex, 3);
        if (item == nullptr)return;
        if (checkBox->isChecked()) {
            //设置Item可编辑
            item->setFlags(Qt::ItemIsEditable);
        }
        else {
            //计算角度并重新设置角度

            //设置item不可修改
            item->setFlags(Qt::ItemIsEnabled);
        }
    }

    void SEAPointJunctionDialog::InitCreate()
    {
        if (_DiscModel == nullptr && _DiscModel->getJunctionManager() == nullptr)return;
        QString name = "SEA Point-0";
        name = _DiscModel->getJunctionManager()->checkName(name);
        _ui->lineEdit_Name->setText(name);
    }

    void SEAPointJunctionDialog::InitEdit()
    {
        if (_DiscModel == nullptr && _DiscModel->getJunctionManager() == nullptr)return;
        Acoustics::FITKSEAJunctionPoint* junData = dynamic_cast<Acoustics::FITKSEAJunctionPoint*>(_DiscModel->getJunctionManager()->getDataByID(_currentDataID));
        if (junData == nullptr)return;
        QString name = junData->getDataObjectName();
        _ui->lineEdit_Name->setText(name);

        setDataToWidget(junData);
    }

    bool SEAPointJunctionDialog::OKCreate()
    {
        if (_DiscModel == nullptr && _DiscModel->getJunctionManager() == nullptr)return false;
        QString name = _ui->lineEdit_Name->text();
        if (_DiscModel->getJunctionManager()->getDataByName(name)) {
            QMessageBox box(QMessageBox::Warning, "", QString(tr("\"%1\" Name exists!")).arg(name), QMessageBox::Ok);
            box.exec();
            return false;
        }

        Acoustics::FITKSEAJunctionPoint* junData = new Acoustics::FITKSEAJunctionPoint();
        junData->setDataObjectName(name);
        junData->setAutoCreate(false);
        _currentDataID = junData->getDataObjectID();
        getDataFromWidget(junData);
        _DiscModel->getJunctionManager()->appendDataObj(junData);
        return true;
    }

    bool SEAPointJunctionDialog::OKEdit()
    {
        if (_DiscModel == nullptr && _DiscModel->getJunctionManager() == nullptr)return false;
        //QString name = _ui->lineEdit_Name->text();
        //if (_DiscModel->getJunctionManager()->getDataByName(name)) {
        //    QMessageBox box(QMessageBox::Warning, "", QString(tr("\"%1\" Name exists!")).arg(name), QMessageBox::Ok);
        //    box.exec();
        //    return false;
        //}
        auto junData = dynamic_cast<Acoustics::FITKSEAJunctionPoint*>(_DiscModel->getJunctionManager()->getDataByID(_currentDataID));
        if (junData == nullptr)return false;
        //junData->setDataObjectName(name);
        getDataFromWidget(junData);
        return true;
    }

    void SEAPointJunctionDialog::getDataFromWidget(Acoustics::FITKSEAJunctionPoint * data)
    {
        if (data == nullptr || _userDefWidget == nullptr)return;

        int conRowCount = _ui->tableWidget_Connect->rowCount();
        QList<Acoustics::FITKSEAJunPointConStr> conInfo;
        for (int i = 0; i < conRowCount; i++) {
            Acoustics::FITKSEAJunPointConStr conStr;
            //子系统id与连接点id
            QTableWidgetItem* item = _ui->tableWidget_Connect->item(i, 0);
            if (item) {
                conStr._subSysID = item->data(SEAPointJunction_SubSysPos).toInt();
                conStr._pointID = item->data(SEAPointJunction_PointPos).toInt();
            }
            //厚度
            item = _ui->tableWidget_Connect->item(i, 1);
            if (item) {
                conStr._radius = item->text().toDouble();
            }
            //是否角度可修改
            QCheckBox* checkBox = dynamic_cast<QCheckBox*>(_ui->tableWidget_Connect->cellWidget(i, 2));
            if (checkBox) {
                conStr._isAlphaOve = checkBox->isChecked();
            }
            //角度
            item = _ui->tableWidget_Connect->item(i, 3);
            if (item) {
                conStr._alpha = item->text().toDouble();
            }
            conInfo.append(conStr);
        }
        data->replaceConnections(conInfo);

        data->setEnabledJunction(_ui->checkBox_EnabledJunction->isChecked());
        QTableWidgetItem* item = _ui->tableWidget_Node->item(0, 0);
        if (item) {
            data->setPointID(item->text().toInt());
        }

        //存储user-defined界面数据
        _userDefWidget->getDataFromWidget(data);
    }

    void SEAPointJunctionDialog::setDataToWidget(Acoustics::FITKSEAJunctionPoint * data)
    {
        if (data == nullptr || _userDefWidget == nullptr)return;

        QList<Acoustics::FITKSEAJunPointConStr> conInfo = data->getConnections();
        updateConnectTable(conInfo);

        bool isEnable = data->getEnabledJunction();
        _ui->checkBox_EnabledJunction->setChecked(isEnable);

        int nodeID = data->getPointID();
        updateNodeTable(nodeID);

        //初始化user-defined界面
        _userDefWidget->initTable(data->getSubSysIds());
        //user-defined中填充数据
        _userDefWidget->setDataToWidget(data);
    }

    void SEAPointJunctionDialog::updateConnectTable(QList<Acoustics::FITKSEAJunPointConStr>& junction)
    {
        if (_SEAModel == nullptr && _SEAModel->getSEASubSysManager() == nullptr) false;
        _ui->tableWidget_Connect->setRowCount(0);
        int rowIndex = 0;
        for (Acoustics::FITKSEAJunPointConStr str : junction) {
            Acoustics::FITKAbstractSEASubSys* subSys = _SEAModel->getSEASubSysManager()->getDataByID(str._subSysID);
            if(subSys == nullptr)continue;
            Acoustics::FITKAbstractSEASubSys::SEASubSysType type = subSys->getSEASubSysType();
            _ui->tableWidget_Connect->setRowCount(rowIndex + 1);
            QTableWidgetItem* item = new QTableWidgetItem();
            item->setText(subSys->getDataObjectName());
            item->setData(SEAPointJunction_SubSysPos, subSys->getDataObjectID());
            item->setData(SEAPointJunction_PointPos, str._pointID);
            item->setFlags(Qt::ItemIsEnabled);
            _ui->tableWidget_Connect->setItem(rowIndex, 0, item);

            item = new QTableWidgetItem();
            item->setText(QString::number(str._radius));
            item->setData(SEAPointJunction_SubSysPos, subSys->getDataObjectID());
            item->setData(SEAPointJunction_PointPos, str._pointID);
            if (type == Acoustics::FITKAbstractSEASubSys::SEABeam)item->setFlags(Qt::ItemIsEditable);
            _ui->tableWidget_Connect->setItem(rowIndex, 1, item);

            if (type != Acoustics::FITKAbstractSEASubSys::SEABeam) {
                QCheckBox* checkBox = new QCheckBox(this);
                checkBox->setChecked(str._isAlphaOve);
                checkBox->setProperty("row", rowIndex);
                connect(checkBox, SIGNAL(clicked(bool)), this, SLOT(slotAlphaOveCheck()));
                _ui->tableWidget_Connect->setCellWidget(rowIndex, 2, checkBox);

                //item = new QTableWidgetItem();
                //item->setText(subSys->getDataObjectName());
                //item->setData(SEAPointJunction_SubSysPos, subSys->getDataObjectID());
                //item->setData(SEAPointJunction_PointPos, str._pointID);
                //if (str._isAlphaOve) item->setFlags(Qt::ItemIsEnabled);
                //else item->setFlags(Qt::ItemIsEditable);
                //_ui->tableWidget_Connect->setItem(rowIndex, 3, item);
            }
            rowIndex++;
        }
    }

    void SEAPointJunctionDialog::updateNodeTable(int pointID)
    {
        if (_DiscModel == nullptr && _DiscModel->getNodes() == nullptr) return;
        Core::FITKNode* node = _DiscModel->getNodes()->getNodeByID(pointID);
        if (node == nullptr)return;
        QTableWidgetItem* item = new QTableWidgetItem();
        item->setText(QString::number(pointID));
        item->setFlags(Qt::ItemIsEnabled);
        _ui->tableWidget_Node->setItem(0, 0, item);

        item = new QTableWidgetItem();
        item->setText(QString::number(node->x()));
        item->setFlags(Qt::ItemIsEnabled);
        _ui->tableWidget_Node->setItem(0, 1, item);

        item = new QTableWidgetItem();
        item->setText(QString::number(node->y()));
        item->setFlags(Qt::ItemIsEnabled);
        _ui->tableWidget_Node->setItem(0, 2, item);

        item = new QTableWidgetItem();
        item->setText(QString::number(node->z()));
        item->setFlags(Qt::ItemIsEnabled);
        _ui->tableWidget_Node->setItem(0, 3, item);
    }
}
